home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SPACE 1
/
SPACE - Library 1 - Volume 1.iso
/
program
/
386
/
utility
/
speed_2.s
< prev
next >
Wrap
Text File
|
1985-11-19
|
8KB
|
195 lines
; Program Name: SPEED_2.S
; Version 1.003
; NOTE: This program is similar to SPEED_1. The differences between the
; the two is that this one uses a different algorithm to process
; the command line, and it fetches the start time at a more appropriate
; place in the program.
; Assembly Instructions:
; Assemble in "PC-relative" mode and save with a TTP extension.
; Function:
; Spawn a process and calculate the spawned program's load and execution
; times. Pause for a keypress before terminating.
release_excess_memory:
lea program_end, a0 ; Put "end of program" address in A0.
movea.l 4(a7), a1 ; Put "basepage" address in A1.
movea.l a1, a4 ; Copy to A4 for command line access.
trap #6 ; Calculate program size and release memory.
; NOTE: A local stack is not declared in PRG_5AP.TOS. Because of the long
; string that is printed by that program, this program will bomb when
; it spawns PRG_5AP.TOS, if a local stack is not declared here.
lea stack, a7 ; Point A7 to this program's stack.
; NOTE ABOUT THE COMMAND LINE PROCESSING ALGORITHM
; Refer to figure 2.13 of chapter 2 for an image of a command line
; that is stored in a program's basepage. The first byte of the command
; line is a count of the ASCII characters contained therein. The second
; byte is the first character in the command line. The last character in
; the command line is followed by the ASCII code for a carriage return;
; the carriage return is not included in the character count.
; For program SPEED_2 we know that the command line character count
; cannot exceed 12 characters = 12 bytes = 3 longwords. Therefore, it
; would be convenient if those 3 longwords could be transfered directly to
; three data registers. Unfortunately, the MC68000 will not permit the
; movem instruction to transfer data which begins at an odd address.
; Because of this restriction, it would be convenient if the operating
; system stored the first command line character at an even address.
; Unfortunately, it does not. Therefore, we are forced to fetch 4 longwords
; from the vicinity of the command line. That's why we must use four data
; registers instead of three.
; To complicate things, the command line ASCII string will be corrupted
; by the first byte in the first register, because it is the character count,
; not a valid character. So, when the data contained in the data registers
; are transferred to a declared variable location, this byte must be stripped
; from the command line ASCII string.
; I accomplish this with no wasted time by declaring two variable
; locations, input_line and program_name. Since input_line is one byte in
; length, and the first location for program_name immediately follows that
; byte, when the contents of the data registers is moved to the location of
; input_line, the variable program_name will point to the first character
; of the command line ASCII string, as it should.
; The carriage return at the end of the ASCII string is also transferred
; to the 15 byte array addressed by program_name. It must be overwritten by
; a NULL so that the ASCII string is NULL terminated. That is accomplished
; fetching the command line character count as a byte length value, extending
; it to word length and using the result in an operand that uses "address
; register indirect with index" addressing.
process_command_line:
lea input_line, a3 ; Fetch location to contain command line.
lea output_line, a5 ; A second location: for filename.
movem.l $80(a4), d0-d3 ; Move 16 bytes of command line to 4 registers.
movem.l d0-d3, (a3) ; Move them to address "input_line".
movem.l d0-d3, (a5) ; Move them to address "output_line".
move.b $80(a4), d0 ; Fetch command line ASCII character count.
ext.w d0 ; Extend to word for next instruction.
move.b #0, 1(a3,d0.w) ; Store a null at end of command line input.
move.b #0, 1(a5,d0.w) ; Same for filename buffer.
insert_filename_suffix:
move.b #$44, -2(a5,d0.w) ; Insert letter 'D'.
move.b #$41, -1(a5,d0.w) ; Insert letter 'A'.
move.b #$54, 0(a5,d0.w) ; Insert letter 'T'.
create_file:
move.w #0, -(sp) ; File attribute = read/write.
pea filename ; Will be name of spawned process + .DAT.
move.w #$3C, -(sp) ; Function = f_create = GEMDOS $3C.
trap #1 ; File handle is returned in D0.
addq.l #8, sp
lea file_handle, a0
move.w d0, (a0)
redirect_output: ; Exchange file handle with screen's handle.
move.w file_handle, -(sp) ; This is the disk file's handle.
move.w #1, -(sp) ; This is the video screen's handle.
move.w #$46, -(sp) ; Function = f_force = GEMDOS $46.
trap #1
addq.l #6, sp
; NOTE: In order to increase the accuracy of the start time, the stack is
; prepared for the spawning process, then, just before trap #1 is
; invoked, custom trap #3 is invoked and the start time is saved.
prepare_stack_for_load_and_execute_program:
pea environ_string
pea command_line
pea program_name
move.w #0, -(sp)
move.w #$4B, -(sp) ; Function = GEMDOS $4B = p_exec.
get_start_time:
lea start_time, a3 ; Fetch address of variable "start_time".
trap #3 ; Returns value of system clock in D0.
move.w d0, (a3) ; Save start time.
load_and_execute_program:
trap #1
move.w d0, d3 ; Copy after-load value to D3 for calculation.
get_end_time:
trap #3 ; Returns value of system clock in D0.
move.w d0, d5 ; Copy to D5 for calculation.
sub.w d3, d5 ; Subtract after-load time from end time.
ext.l d5 ; Extend to 32 bits.
reposition_stack_pointer:
lea $10(sp), sp
get_drive:
move.w #$19, -(sp) ; Function = dgetdrv = GEMDOS $19.
trap #1
addq.l #2, sp
add.b #'A', d0
lea drive, a0
move.b d0, (a0)
print_heading:
lea heading, a0
bsr print_string
lea program_name, a0
bsr print_string
print_drive_for_spawned_program:
lea drive_msg, a0
bsr print_string
compute_load_time:
lea load_time_msg, a0
bsr print_string
lea start_time, a3
sub.w (a3), d3 ; Subtract start time from after-load time.
ext.l d3 ; Extent to 32 bits.
trap #9 ; See description in TRAPS.S.
close_file:
move.w file_handle, -(sp)
move.w #$3E, -(sp) ; Function = fclose = GEMDOS $3E.
trap #1
addq.l #4, sp
terminate:
move.w #0, -(sp)
trap #1
print_string: ; Expects address of string to be in A0.
move.l a0, -(sp) ; Push address of string onto stack.
move.w #9, -(sp) ; Function = c_conws = GEMDOS $9.
trap #1 ; GEMDOS call
addq.l #6, sp ; Reset stack pointer to top of stack.
rts
data
heading: dc.b $D,$A,"SPEED_2.TTP Execution Results",$D,$A
dc.b "for ",0
drive_msg: dc.b ", loaded from drive: "
drive: dc.b "A",$D,$A,0
load_time_msg: dc.b $D,$A," Load time: ",0
environ_string: dc.b "TERM",0
command_line: dc.b 0
align
bss
start_time: ds.w 1
file_handle: ds.w 1
input_line: ds.b 1
program_name: ds.b 15 ; Program name buffer.
output_line: ds.b 1
filename: ds.b 15 ; Filename buffer.
ds.l 96 ; Program stack.
stack: ds.l 0 ; Address of program stack.
program_end: ds.l 0
end